﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace sand_game_core
{
    public struct newParticle
    {
        public byte R;
        public byte G;
        public byte B;
        public byte A;
        public byte myType;
        internal float L;
        internal static Color litColor;
        private static byte light;
        public static void setParticle(ref newParticle p, byte MyType, byte Red, byte Green, byte Blue, byte Alpha)
        {
            p.R = Red;
            p.G = Green;
            p.B = Blue;
            p.A = Alpha;
            p.myType = MyType;
            p.L = 0;
        }
        public static void setParticle(ref newParticle p, byte MyType)
        {
            setParticle(ref p, MyType, p.L);
        }
        public static void setParticle(ref newParticle p, byte MyType, float light)
        {
            switch (MyType)
            {
                case 0: //done
                    p.R = 0;
                    p.G = 0;
                    p.B = 0;
                    p.A = 0;
                    break;
                case 1: //done
                    p.R = (byte)(176 + random.rnd.Next(60));
                    p.G = (byte)(170 + random.rnd.Next(60));
                    p.B = (byte)(70 + random.rnd.Next(60));
                    p.A = 255;
                    break;
                case 2: //done
                    p.R = (byte)(169 + random.rnd.Next(38));
                    p.G = (byte)(169 + random.rnd.Next(38));
                    p.B = (byte)(166 + random.rnd.Next(32));
                    p.A = 255;
                    break;
                case 3: //done
                    p.R = (byte)(0 + random.rnd.Next(60));
                    p.G = (byte)(50 + random.rnd.Next(60));
                    p.B = (byte)(100 + random.rnd.Next(60));
                    p.A = 130;
                    break;
                case 4:
                    p.R = (byte)(180 + random.rnd.Next(75));
                    p.G = (byte)(100 + random.rnd.Next(60));
                    p.B = (byte)(50 + random.rnd.Next(60));
                    p.A = 130;
                    break;
                case 5:
                    p.R = (byte)(230 + random.rnd.Next(25));
                    p.G = (byte)(130 + random.rnd.Next(60));
                    p.B = (byte)(60 + random.rnd.Next(60));
                    p.A = 90;
                    break;
                case 6:
                    p.R = (byte)(30 + random.rnd.Next(30));
                    p.G = (byte)(30 + random.rnd.Next(30));
                    p.B = (byte)(30 + random.rnd.Next(30));
                    p.A = 255;
                    break;
                case 7:
                    p.R = (byte)(70 + random.rnd.Next(30));
                    p.G = (byte)(70 + random.rnd.Next(30));
                    p.B = (byte)(70 + random.rnd.Next(30));
                    p.A = 255;
                    break;
            }
            p.myType = MyType;
            p.L = light;
        }
    }
    public static class NewParticle
    {
        #region fields
        public static Texture2D myImage;
        private static newParticle upParticle;
        private static newParticle downParticle;
        private static byte ammount;
        private static newParticle RightParticle;
        private static newParticle LeftParticle;
        private static newParticle p;
        private static int[] lights;
        private static float ThisParticle, temp, temp2, temp3;
        public static newParticle blank;
        public delegate void Update(uint x, uint y);
        public static Update toUpdate;
        public delegate void BaseLight(uint x, uint y);
        public static BaseLight Light;
        #endregion
        public static void init()
        {
            blank = new newParticle();
            newParticle.setParticle(ref blank, 0, 0, 0, 0, 0);
            toUpdate = new Update(update);
            Light = new BaseLight(lightMe);
            newParticle.litColor = new Color();
            lights = new int[5];
        }
        public static void update(uint x, uint y)
        {
            p = world.worldParticleLayer[x * world.arraywidth + y];
            switch (p.myType)
            {
                #region 0: empty
                case 0: //empty
                    break;
                #endregion
                #region 1: sand
                case 1: //sand
                    ammount = (byte)random.rnd.Next(2);
                    upParticle = world.arrayheight > y + 1 ? world.worldParticleLayer[x * world.arraywidth + y + 1] : blank;
                    downParticle = y >= 1 ? world.worldParticleLayer[x * world.arraywidth + y - 1] : blank;
                    RightParticle = x >= 1 ? world.worldParticleLayer[(x - ammount) * world.arraywidth + y] : blank;
                    LeftParticle = world.arraywidth > y + 1 ? world.worldParticleLayer[(x + ammount) * world.arraywidth + y] : blank;

                    if (LeftParticle.myType == 6)
                    {
                        newParticle.setParticle(ref world.worldParticleLayer[(x + ammount) * world.arraywidth + y], 7);
                        newParticle.setParticle(ref world.worldParticleLayer[x * world.arraywidth + y], 7);
                    }
                    else if (RightParticle.myType == 6)
                    {
                        newParticle.setParticle(ref world.worldParticleLayer[(x - ammount) * world.arraywidth + y], 7);
                        newParticle.setParticle(ref world.worldParticleLayer[x * world.arraywidth + y], 7);
                    }

                    else if (upParticle.myType == 6)
                    {
                        newParticle.setParticle(ref world.worldParticleLayer[x * world.arraywidth + y + 1], 7);
                        newParticle.setParticle(ref world.worldParticleLayer[x * world.arraywidth + y], 7);
                    }
                    else if (downParticle.myType == 6)
                    {
                        newParticle.setParticle(ref world.worldParticleLayer[x * world.arraywidth + y - 1], 7);
                        newParticle.setParticle(ref world.worldParticleLayer[x * world.arraywidth + y], 7);
                    }
                    if (downParticle.myType == 0 || downParticle.myType == 3)
                    {
                        world.swap(x, y, x, y - 1);
                    }
                    else if (downParticle.myType == 1 && random.rnd.Next(50) == 1)
                    {
                        world.swap(x, y, (uint)(x + (random.rnd.Next(0, 100) < 50 && !(LeftParticle.myType == 1) ? -1 : !(LeftParticle.myType == 1) ? 1 : 0)), y);
                    }
                    break;
                #endregion
                #region 2: stone
                case 2:
                    /*downParticle = y >= 1 ? world.worldParticleLayer[x * world.arraywidth + y - 1] : blank;
                    if (downParticle.myType == 0 || downParticle.myType == 3)
                    {
                        world.swap(x, y, x, y - 1);
                    }*/
                    break;
                #endregion
                #region 3: water
                case 3:
                    downParticle = y >= 1 ? world.worldParticleLayer[x * world.arraywidth + y - 1] : NewParticle.blank;
                    ammount = (byte)random.rnd.Next(7);
                    if (downParticle.myType == 4)
                    {
                        newParticle.setParticle(ref world.worldParticleLayer[x * world.arraywidth + y - 1], 6);
                        newParticle.setParticle(ref world.worldParticleLayer[x * world.arraywidth + y], 6);
                    }
                    if (downParticle.myType == 0)
                    {
                        world.swap(x, y, x, y - 1);
                        world.swap(x, y - 1, (uint)(x + ammount - 3), y);
                    }
                    else
                    {
                        world.swap(x, y, (uint)(x + ammount - 3), y);
                    }
                    if (ammount != 4)
                    {
                        RightParticle = (x - ammount - 3) * world.arraywidth + y < world.worldParticleLayer.Length ? world.worldParticleLayer[(x - ammount - 3) * world.arraywidth + y] : blank;
                        LeftParticle = (x + ammount - 3) * world.arraywidth + y < world.worldParticleLayer.Length ? world.worldParticleLayer[(x + ammount - 3) * world.arraywidth + y] : blank;
                        if (LeftParticle.myType == 4)
                        {
                            newParticle.setParticle(ref world.worldParticleLayer[(x + ammount - 3) * world.arraywidth + y], 6);
                            newParticle.setParticle(ref world.worldParticleLayer[x * world.arraywidth + y], 6);
                        }
                        else if (RightParticle.myType == 4)
                        {
                            newParticle.setParticle(ref world.worldParticleLayer[(x - ammount - 3) * world.arraywidth + y], 6);
                            newParticle.setParticle(ref world.worldParticleLayer[x * world.arraywidth + y], 6);
                        }
                    }
                    break;
                #endregion
                #region 4: lava
                case 4:
                    upParticle = world.arrayheight > y + 1 ? world.worldParticleLayer[x * world.arraywidth + y + 1] : blank;

                    downParticle = y >= 1 ? world.worldParticleLayer[x * world.arraywidth + y - 1] : blank;

                    ammount = (byte)random.rnd.Next(2);
                    RightParticle = x >= ammount ? world.worldParticleLayer[(x - ammount) * world.arraywidth + y] : blank;
                    LeftParticle = world.arraywidth > y + ammount ? world.worldParticleLayer[(x + ammount) * world.arraywidth + y] : blank;
                    if (downParticle.myType == 1)
                    {
                        newParticle.setParticle(ref world.worldParticleLayer[x * world.arraywidth + y - 1], 4);
                    }
                    else if (LeftParticle.myType == 3)
                    {
                        newParticle.setParticle(ref world.worldParticleLayer[(x + ammount) * world.arraywidth + y], 6);
                        newParticle.setParticle(ref world.worldParticleLayer[x * world.arraywidth + y], 6);
                    }
                    else if (RightParticle.myType == 3)
                    {
                        newParticle.setParticle(ref world.worldParticleLayer[(x - ammount) * world.arraywidth + y], 6);
                        newParticle.setParticle(ref world.worldParticleLayer[x * world.arraywidth + y], 6);
                    }
                    else if (downParticle.myType == 3)
                    {
                        newParticle.setParticle(ref world.worldParticleLayer[x * world.arraywidth + y - 1], 6);
                        newParticle.setParticle(ref world.worldParticleLayer[x * world.arraywidth + y], 6);
                    }
                    else if (LeftParticle.myType == 1)
                    {
                        newParticle.setParticle(ref world.worldParticleLayer[(x + ammount) * world.arraywidth + y], 4);
                    }
                    else if (RightParticle.myType == 1)
                    {
                        newParticle.setParticle(ref world.worldParticleLayer[(x - ammount) * world.arraywidth + y], 4);
                    }
                    else if (upParticle.myType == 1)
                    {
                        newParticle.setParticle(ref world.worldParticleLayer[x * world.arraywidth + y + 1], 4);
                    }
                    else if (upParticle.myType == 0 && random.rnd.Next(100) == 0)
                    {
                        newParticle.setParticle(ref world.worldParticleLayer[x * world.arraywidth + y - 1], 5);
                    } if (ammount > 0)
                    {
                        world.swap(x, y, (uint)((x + RightParticle.myType < 2 && LeftParticle.myType >= 2) ? ammount : -ammount), y);
                    }
                    else if ((downParticle.myType == 0 || downParticle.myType == 7))
                    {
                        world.swap(x, y, x, y - 1);
                    }

                    break;
                #endregion
                #region 5: fire
                case 5:
                    upParticle = world.arrayheight > y + 1 ? world.worldParticleLayer[x * world.arraywidth + y + 1] : blank;
                    downParticle = y >= 1 ? world.worldParticleLayer[x * world.arraywidth + y - 1] : blank;
                    ammount = (byte)random.rnd.Next(3);
                    if (ammount > 0)
                    {
                        //if (upParticle == null)
                        {
                            world.swap(x, y, x, y + 1);
                        }
                        RightParticle = x >= ammount ? world.worldParticleLayer[(x - ammount) * world.arraywidth + y] : blank;
                        LeftParticle = world.arraywidth > y + ammount ? world.worldParticleLayer[(x + ammount) * world.arraywidth + y] : blank;
                        world.swap(x, y, (uint)(x + (RightParticle.myType == 0 && !(LeftParticle.myType == 0) || random.rnd.Next(2) == 0 ? -ammount : ammount)), y);
                    }
                    if (random.rnd.Next(25) == 0 || upParticle.myType == 3)
                        newParticle.setParticle(ref world.worldParticleLayer[x * world.arraywidth + y], 0);
                    break;
                #endregion
                #region 6: obsidian
                case 6:
                    break;
                #endregion
                #region 7: ash
                case 7:
                    upParticle = world.arrayheight > y + 1 ? world.worldParticleLayer[x * world.arraywidth + y + 1] : blank;
                    downParticle = y >= 1 ? world.worldParticleLayer[x * world.arraywidth + y - 1] : blank;
                    ammount = (byte)random.rnd.Next(2);
                    RightParticle = ammount > 0 ? (x >= ammount ? world.worldParticleLayer[(x - ammount) * world.arraywidth + y] : blank) : blank;
                    LeftParticle = ammount > 0 ? (world.arraywidth > y + ammount ? world.worldParticleLayer[(x + ammount) * world.arraywidth + y] : blank) : blank;
                    if (downParticle.myType == 6)
                        newParticle.setParticle(ref world.worldParticleLayer[x * world.arraywidth + y - 1], 7);
                    if (upParticle.myType == 6)
                        newParticle.setParticle(ref world.worldParticleLayer[x * world.arraywidth + y + 1], 7);
                    if (LeftParticle.myType == 6)
                        newParticle.setParticle(ref world.worldParticleLayer[(x + ammount) * world.arraywidth + y], 7);
                    if (RightParticle.myType == 6)
                        newParticle.setParticle(ref world.worldParticleLayer[(x - ammount) * world.arraywidth + y], 7);
                    if (downParticle.myType == 0 || downParticle.myType == 3)
                    {
                        world.swap(x, y, x, y - 1);
                    }
                    else if (downParticle.myType == 7 && ammount > 0)
                    {
                        world.swap(x, y, (uint)(x + ((random.rnd.Next(0, 100) < 50) && !(LeftParticle.myType == 7) ? ammount : !(RightParticle.myType == 7) ? -ammount : 0)), y);
                    }

                    break;
                #endregion
            }
        }
        public static void lightMe(uint x, uint y)
        {
            //ThisParticle = Math.Max(world.worldParticleLayer[x * world.arraywidth + y - 1].L ,Math.Max(Math.Max(world.worldParticleLayer[(x - 1) * world.arraywidth + y].L,world.worldParticleLayer[(x + 1) * world.arraywidth + y].L) , Math.Max(world.worldParticleLayer[x * world.arraywidth + y].L, world.worldParticleLayer[x * world.arraywidth + y + 1].L)));
            ThisParticle = (int)world.worldParticleLayer[x * world.arraywidth + y].L;
            if(world.worldParticleLayer[(x+1) * world.arraywidth + y].L > ThisParticle)
                ThisParticle = (int)world.worldParticleLayer[(x+1) * world.arraywidth + y].L;

            if (world.worldParticleLayer[(x - 1) * world.arraywidth + y].L > ThisParticle)
                ThisParticle = (int)world.worldParticleLayer[(x-1) * world.arraywidth + y].L;

            if (world.worldParticleLayer[x * world.arraywidth + y+1].L > ThisParticle)
                ThisParticle = (int)world.worldParticleLayer[x * world.arraywidth + y+1].L;

            if (world.worldParticleLayer[x * world.arraywidth + y-1].L > ThisParticle)
                ThisParticle = (int)world.worldParticleLayer[x * world.arraywidth + y-1].L;
            /*ThisParticle =  (?  : 0) > ThisParticle ? world.worldParticleLayer[x * world.arraywidth + y + 1].L : ThisParticle;
            ThisParticle =                   (x >= 1 ?  : 0) > ThisParticle ? world.worldParticleLayer[(x - 1) * world.arraywidth + y].L : ThisParticle;
            ThisParticle = ( ?  : 0) > ThisParticle ? world.worldParticleLayer[(x + 1) * world.arraywidth + y].L : ThisParticle;
            ThisParticle =                     (y >= 1 ?  : 0) > ThisParticle ? world.worldParticleLayer[x * world.arraywidth + y - 1].L : ThisParticle;
             */
            if (ThisParticle > 5 && ThisParticle < 250)
            {
                switch (world.worldParticleLayer[x * world.arraywidth + y].myType)
                {
                    case 5:
                        ThisParticle += 4;
                        break;
                    case 4:
                        ThisParticle += 1;
                        break;
                    case 0: //empty
                        ThisParticle -= 0.1f;
                        break;
                    case 3: //water
                    case 7: //ash
                        ThisParticle -= 2;
                        break;
                    case 1: //sand
                    case 2: //stone
                        ThisParticle -= 4;
                        break;
                }
                world.worldParticleLayer[x * world.arraywidth + y].L = ThisParticle < 250 ? ThisParticle > 5 ? ThisParticle : 0 : 250;
            }
        }
    }
}
